<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="description" content="coinfaces">

        <title>树莓派DNS和DHCP服务器</title>

    <link rel="stylesheet" href="../../theme/css/style.css">
    <link rel="stylesheet" href="../../theme/css/pygments.css">



</head>

<body>
    <div class="content">
<h1>树莓派DNS和DHCP服务器</h1>    <p>
        under
            <a href="../../tags/raspi/">raspi</a>
    </p>
    <p>
        in <a href="../../categories/tech/">tech</a>
    </p>
    <p>Published: 2020-12-14</p>


    <p>在一台旧电脑上部署了一些服务，这些服务是通过端口区分的，想改成nginx反向代理并且用域名区分，这就需要解决域名解析的问题。编辑hosts文件是一种方案，但这种方案并不贴切，因为这些域名只在这个局域网中有用，一旦离开了这个局域网，这些hosts文件的记录就失去了意义。另外这种方案也比较麻烦，每一台需要访问服务的设备都需要修改hosts文件，而且对于有的移动设备来说，这是不可能实现的任务。最佳的解决方案是配置一台DNS服务器，接下来还需要通知每一台设备使用该DNS服务，这个工作是DHCP服务器来做的，如果路由器的DHCP服务允许指定一台其局域网内的DNS服务器，事情会变得简单一些，但不幸的是这也没能实现。</p>
<p>于是需要同时配置DNS服务和DHCP服务，好在有一个软件提供了现成的解决方案，那就是dnsmasq。接下来就介绍如何在一台树莓派（Raspbian Jessie）上用dnsmasq部署DNS和DHCP服务。为了方便叙述，这里假设局域网内默认网关（也就是路由器）的IP是192.168.0.1，上游DNS服务器（ISP网络接入设备）的IP地址是192.168.1.1，而树莓派的地址是192.168.0.100。</p>
<p>这里涉及到的一些软件的package名称为dnsmasq、openresolv。</p>
<h2>配置DNS服务</h2>
<p>dnsmasq需要一台上游的DNS服务器来解析它不知道的域名，该上游服务器的IP地址在/etc/resolv.conf中，这里用openresolv来管理/etc/resolv.conf配置文件。编辑/etc/resolvconf.conf文件，指定如下配置：</p>
<div class="highlight"><pre><span></span><code><span class="err"># 指定上游的DNS服务器地址，因为不会收到其它DHCP服务器的配置信息</span>
<span class="err">name_servers=&quot;127.0.0.1 192.168.1.1&quot;</span>
<span class="err">dnsmasq_conf=/etc/dnsmasq.resolvconf.conf</span>
<span class="err">dnsmasq_resolv=/var/run/dnsmasq/resolv.conf</span>
</code></pre></div>


<p>然后运行<code>resolvconf -u</code>命令来生成/etc/resolv.conf文件以及两个dnsmasq需要用到的配置文件。</p>
<p>接下来需要告诉dnsmasq使用openresolv生成的配置文件，修改/etc/dnsmasq.conf，指定如下配置：</p>
<div class="highlight"><pre><span></span><code><span class="err">conf-file=/etc/dnsmasq.resolvconf.conf</span>
<span class="err">resolv-file=/var/run/dnsmasq/resolv.conf</span>
</code></pre></div>


<p>可以看一下生成的这些配置文件是什么样的</p>
<div class="highlight"><pre><span></span><code>$ cat /etc/dnsmasq.resolvconf.conf
<span class="c1"># Generated by resolvconf</span>
$ cat /var/run/dnsmasq/resolv.conf
<span class="c1"># Generated by resolvconf</span>
nameserver <span class="m">192</span>.168.1.1
$ cat /etc/resolv.conf
<span class="c1"># Generated by resolvconf</span>
nameserver <span class="m">127</span>.0.0.1
</code></pre></div>


<p>最后将dnsmasq暴露给局域网中的服务器，在/etc/dnsmasq.conf中指定如下配置：</p>
<div class="highlight"><pre><span></span><code><span class="err"># 注意不要漏写127.0.0.1</span>
<span class="err">listen-address=127.0.0.1,192.168.0.100</span>
</code></pre></div>


<h3>测试DNS服务</h3>
<p>1、测试局域网DNS服务是否有效</p>
<p>在局域网中另找一台机器，运行以下命令，成功即可</p>
<div class="highlight"><pre><span></span><code><span class="n">drill</span> <span class="n">www</span><span class="p">.</span><span class="n">archlinux</span><span class="p">.</span><span class="n">org</span> <span class="mf">@192.168.0.100</span>
</code></pre></div>


<p>2、测试缓存是否有效</p>
<p>清空dnsmasq的缓存</p>
<div class="highlight"><pre><span></span><code><span class="err">kill -SIGHUP `cat /var/run/dnsmasq/dnsmasq.pid`</span>
</code></pre></div>


<p>然后连续运行2遍第1步的命令，如果第二次查询时间显著缩短，表示dnsmasq的域名缓存起作用了。</p>
<h2>配置DHCP服务</h2>
<p>在/etc/dnsmasq.conf中指定如下配置：</p>
<div class="highlight"><pre><span></span><code><span class="err"># 设置提供DHCP服务的网卡，可参考ip link的返回结果</span>
<span class="err">interface=eth0</span>
<span class="err"># 只监听指定的网卡，在同时配置DNS服务和DHCP服务时有效</span>
<span class="err">bind-interfaces</span>
<span class="err"># 返回默认网关地址</span>
<span class="err">dhcp-option=option:router,192.168.0.1</span>
<span class="err"># 返回本机地址作为DNS服务器地址</span>
<span class="err">dhcp-option=6,0.0.0.0</span>
<span class="err"># 返回一条静态路由规则</span>
<span class="err"># 例如通过192.168.10.20访问子网192.168.10.0/24</span>
<span class="err"># dhcp-option=121,192.168.10.0/24,192.168.10.20</span>
<span class="err"># 可分配IP地址的范围，参考路由器的DHCP配置</span>
<span class="err">dhcp-range=192.168.0.101,192.168.0.199,2h</span>
<span class="err"># 设置IP和MAC地址的绑定，参考路由器的配置</span>
<span class="err">dhcp-host=aa:bb:cc:dd:ee:ff,192.168.111.50</span>
<span class="err">dhcp-host=aa:bb:cc:ff:dd:ee,192.168.111.51</span>
</code></pre></div>


<h3>测试DHCP服务</h3>
<p>暂时关闭路由器的DHCP服务，然后用check_dhcp（monitoring-plugins-basic）</p>
<p>/usr/lib/nagios/plugins/check_dhcp -v -i enp2s0</p>
<p>检查是否有结果返回，以及返回的数据是否符合预期（例如Server Identifier是否和配置DHCP服务的服务器一致）</p>
<h2>配置静态IP</h2>
<p>运行dnsmasq的服务器无法通过DHCP获得IP地址，修改/etc/network/interfaces，为它设置静态IP。</p>
<div class="highlight"><pre><span></span><code><span class="err"># auto eth0确保eth0随ifup启动</span>
<span class="err"># 否则dnsmasq启动时可能无法监听eth0的IP地址上的端口</span>
<span class="err">auto eth0</span>
<span class="err">#iface eth0 inet dhcp</span>
<span class="err">iface eth0 inet static</span>
<span class="err">  address 192.168.0.100</span>
<span class="err">  netmask 255.255.255.0</span>
<span class="err">  gateway 192.168.0.1</span>
</code></pre></div>


<p>创建如下配置文件和响应的上级目录/etc/systemd/system/dnsmasq.service.d/wait-network.conf，内容为：</p>
<div class="highlight"><pre><span></span><code><span class="k">[Unit]</span>
<span class="na">After</span><span class="o">=</span><span class="s">network-online.target</span>
</code></pre></div>


<h2>最后一步</h2>
<p>关闭路由器的DHCP服务（或者设为自动模式，即在局域网有其它DHCP服务器时关闭）</p>
<p>此时dnsmasq成为局域网中新的主要DHCP服务器，修改/etc/dnsmasq.conf，打开以下选项</p>
<div class="highlight"><pre><span></span><code><span class="err">dhcp-authoritative</span>
</code></pre></div>


<p>有些设备（例如电视果）发送的DHCP请求里可能少了一些东西，在关闭dhcp-authoritative的情况下，dnsmasq不会处理其请求</p>
<h2>参考</h2>
<p>https://wiki.archlinux.org/index.php/dnsmasq</p>
<p>https://wiki.archlinux.org/index.php/Openresolv</p>
<p>https://serverfault.com/a/875791</p>
    </div>
<nav class="nav sidebar">
    <div class="siteinfo">
        <div class="sitename"><a href="../..">coinfaces</a></div>
        <div class="tagline">Another Side of Life</div>
    </div>

        <a href="../../categories/">categories</a>
        <a href="../..">&larr; Home</a>
</nav><footer class="footer">
    <span>
        &copy; jpli &middot;
        under <a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">CC-BY-SA 4.0</a>
    </span>
    |
    <span>
        Powered by:
        <a href="http://blog.getpelican.com/">Pelican</a>
    </span>
</footer></body>
</html>